package br.com.binding.rebind.generator;

import java.io.PrintWriter;

import br.com.binding.rebind.BindTypeManager;
import br.com.binding.rebind.BoundModelClass;
import br.com.binding.rebind.ListenerTemplate;
import br.com.binding.rebind.template.Bound_ViewTemplate;

import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JField;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

public class BoundViewGenerator extends Generator {

	private static final String MODEL_INTERFACE = "br.com.binding.client.bind.BindingModel";
	private static final String SOURCES_PROPERTY_CHANGES = "br.com.binding.client.event.SourcesPropertyChanges";

	public String generate(TreeLogger logger, GeneratorContext context,
			String typeName) throws UnableToCompleteException {
		
		TypeOracle oracle = context.getTypeOracle();
		JClassType type = oracle.findType(typeName);
		JClassType modelType = oracle.findType(MODEL_INTERFACE);

		BoundModelClass modelClass = new BoundModelClass(type);
		modelClass.setModelType(modelType);
		BindTypeManager bindManager = BindTypeManager.getInstance();
		
		for(JField field : type.getFields()){
			JClassType fieldClass = field.getType().isClassOrInterface();
			System.out.println(field);
			System.out.println(fieldClass);
			for(String className : bindManager.getAvailableTypes()){
				JClassType bindClass = oracle.findType(className);
				if(fieldClass.isAssignableTo(bindClass)){
					for(ListenerTemplate template : bindManager.getTemplatesForType(className)){
						modelClass.associateFieldListener(field, template);
					}
				}
			}
		}
		
		String packageName = modelClass.getPackageName();
		String newLine = System.getProperty("line.separator");
		
		String finalViewClassName = "Bound_"+modelClass.getClassName()+"_View";
		PrintWriter printer = context.tryCreate(logger, packageName, finalViewClassName);
		
		if (printer == null){
			System.out.println("printer == null");
			return null;
		}
		
		ClassSourceFileComposerFactory composer = null;
		composer = new ClassSourceFileComposerFactory(packageName, finalViewClassName);
		composer.setSuperclass(type.getSimpleSourceName());
		composer.addImport(SOURCES_PROPERTY_CHANGES);

		SourceWriter sourceWriter = composer.createSourceWriter(context, printer);

		Bound_ViewTemplate template = Bound_ViewTemplate.create(newLine);
		System.out.println(template.generate(modelClass));
		sourceWriter.println(template.generate(modelClass));
		
		
		context.commit(logger, printer);
		
		return packageName + "." + finalViewClassName;
	}
}
